package com.cgwx.commonutils.struc;

/**
 * @author GaoWei
 * @Date 2021/8/6 - 10:48
 */
public class Bag
{
    protected Object[] data = null;
    protected int size = 0;

    public Bag()
    {
        this.data = new Object[2];
    }

    public Bag(int initialCapacity)
    {
        this.data = new Object[initialCapacity];
    }

    public void add(Object o)
    {
        insert(o, this.size);
    }

    public int size()
    {
        return this.size;
    }

    public void insert(Object o, int i)
    {
        if ((i < 0) || (i > this.size))
        {
            throw new IllegalArgumentException("required: (i >= 0 && i <= size) but: (i = " + i + ", size = " + this.size + ")");
        }
        ensureCapacity(this.size + 1);
        for (int j = this.size; j > i; j--)
        {
            this.data[j] = this.data[(j - 1)];
        }
        this.data[i] = o;
        this.size += 1;
    }

    public void ensureCapacity(int minCapacity)
    {
        if (minCapacity > this.data.length)
        {
            int x = 2 * this.data.length;
            if (x < minCapacity) {
                x = minCapacity;
            }
            Object[] arr = new Object[x];
            for (int i = 0; i < this.size; i++) {
                arr[i] = this.data[i];
            }
            this.data = arr;
        }
    }

    public int getCapacity()
    {
        return this.data.length;
    }

    private int indexOf(Object o, int i, boolean forward)
    {
        if (this.size == 0) {
            return -1;
        }
        if ((i < 0) || (i >= this.size)) {
            throw new IllegalArgumentException("required: (i >= 0 && i < size) when: (size > 0) but: (i = " + i + ", size = " + this.size + ")");
        }
        if (forward)
        {
            if (o == null) {
                for (; i < this.size; i++) {
                    if (this.data[i] == null) {
                        return i;
                    }
                }
            } else {
                for (; i < this.size; i++) {
                    if (o.equals(this.data[i])) {
                        return i;
                    }
                }
            }
        }
        else if (o == null) {
            for (; i >= 0; i--) {
                if (this.data[i] == null) {
                    return i;
                }
            }
        } else {
            for (; i >= 0; i--) {
                if (o.equals(this.data[i])) {
                    return i;
                }
            }
        }
        return -1;
    }

    public int remove(Object o)
    {
        int i = indexOf(o, 0, true);
        if (i >= 0) {
            remove(i);
        }
        return i;
    }

    public Object remove(int i)
    {
        if ((i < 0) || (i >= this.size)) {
            throw new IllegalArgumentException("required: (i >= 0 && i < size) but: (i = " + i + ", size = " + this.size + ")");
        }
        Object o = this.data[i];
        for (int j = i + 1; j < this.size; j++) {
            this.data[(j - 1)] = this.data[j];
        }
        this.data[(--this.size)] = null;
        return o;
    }

    public Object get(int i)
    {
        if ((i < 0) || (i >= this.size)) {
            throw new IllegalArgumentException("required: (i >= 0 && i < size) but: (i = " + i + ", size = " + this.size + ")");
        }
        return this.data[i];
    }

    public boolean contains(Object o)
    {
        return indexOf(o, 0, true) >= 0;
    }
}
